package Metier.Controleurs;

import Donnees.DaoHDP;
import Donnees.DaoLotCuisson;
import Donnees.DaoPerte;
import Donnees.DaoProduit;
import Donnees.DaoStock;
import Metier.Exceptions.SuppressionDansStockException;
import Metier.Objets.HeurePointe;
import Metier.Objets.LotCuisson;
import Metier.Objets.LotVitrine;
import Metier.Objets.Perte;
import Metier.Objets.Produit;
import Metier.Objets.Stock;
import Metier.Objets.TypeProduit;
import Presentation.FenetrePrincipale;
import Presentation.Onglet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.swing.DefaultListModel;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;

public class GestionCuisson {

    private final DaoLotCuisson daoLotCuisson;
    private final DaoProduit daoProduit;
    private final DaoStock daoStock;
    private final DaoHDP daoHdp;
    private final DaoPerte daoPerte;

    private final GestionVitrine gVitrine;

    private final Onglet onglet;

    private final ResourceBundle cuissonBundle;

    public GestionCuisson(Onglet onglet) {
        this.daoLotCuisson = new DaoLotCuisson();
        this.daoProduit = new DaoProduit();
        this.daoStock = new DaoStock();
        this.daoHdp = new DaoHDP();
        this.daoPerte = new DaoPerte();

        this.gVitrine = new GestionVitrine(onglet);

        this.onglet = onglet;
        if (onglet == null) {
            this.cuissonBundle = ResourceBundle.getBundle("ressources/Cuisson/Cuisson", Locale.FRENCH);
        } else {
            this.cuissonBundle = ResourceBundle.getBundle("ressources/Cuisson/Cuisson", onglet.getFP().getLocale());
        }
    }

    /**
     * Renvoie le model du tableau d'alertes de l'onglet cuisson
     * @param model Ancien model
     * @return Nouveau model
     */
    public DefaultTableModel getAlertes(TableModel model) {
        DefaultTableModel tableModel = new DefaultTableModel() {
            @Override
            public boolean isCellEditable(int row, int column) {
                return false;
            }
        };
        tableModel.addColumn(this.cuissonBundle.getString("cuisson.produit"));
        tableModel.addColumn(this.cuissonBundle.getString("cuisson.quantitevitrine"));
        tableModel.addColumn(this.cuissonBundle.getString("cuisson.seuilalerte"));
        Object[] rowdata = new Object[3];
        List<Produit> listeProduitEnAlerte = new ArrayList<>();
        if (model != null) {
            for (int i = 0; i < model.getRowCount(); i++) {
                listeProduitEnAlerte.add((Produit) model.getValueAt(i, 0));
            }
        }
        try {
            List<Produit> listProduit = daoProduit.chercherViennoiseries();
            List<HeurePointe> listHDP = this.daoHdp.rechercher();
            List<LotVitrine> lotsVitrine = this.gVitrine.getLotsVitrine();
            boolean isHDP = false;
            Calendar g = new GregorianCalendar();
            for (HeurePointe hp : listHDP) {
                if (hp.isEnVigueur(g)) isHDP = true;
            }
            for (Produit p : listProduit) {
                int seuil = isHDP ? p.getSeuilVitrineHDP() : p.getSeuilVitrine();
                int quantiteVitrine = 0;
                for (LotVitrine lot : lotsVitrine) {
                    if (lot.getProduit().equals(p)) {
                        quantiteVitrine += lot.getQuantite();
                    }
                }
                if (quantiteVitrine <= seuil) {
                    rowdata[0] = p;
                    rowdata[1] = quantiteVitrine;
                    rowdata[2] = seuil;
                    tableModel.addRow(rowdata);
                    if (!listeProduitEnAlerte.contains(p) && model != null) {
                        final int finalQuantiteVitrine = quantiteVitrine;
                        Thread t = new Thread(new Runnable() {
                            @Override
                            public void run() {
                                SwingUtilities.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        JOptionPane.showMessageDialog(onglet.getFP(),
                                                "<html><p>" +
                                                        cuissonBundle.getString("cuisson.popupalerte1") + " " +
                                                        finalQuantiteVitrine + " " +
                                                        p + " " +
                                                        cuissonBundle.getString("cuisson.popupalerte2") + " " +
                                                        seuil + " " +
                                                        p + ".</p></html>",
                                                cuissonBundle.getString("cuisson.messagealerte"),
                                                JOptionPane.WARNING_MESSAGE);
                                    }
                                });
                            }
                        });
                        t.start();
                    }
                }
            }
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errAlertes"));
            e.printStackTrace();
        }
        return tableModel;
    }

    /**
     * Renvoie le model de la liste de produits
     * @return Le model de la listePrincipale
     */
    public DefaultListModel getContenuListPrincipale() {
        DefaultListModel listModel = new DefaultListModel();
        listModel.addElement(new Produit(this.cuissonBundle.getString("cuisson.general"), null, 0, 0, 0, 0, 0, 0));
        try {
            List<Produit> list = daoProduit.chercherViennoiseries();
            for (Produit p : list) {
                listModel.addElement(p);
            }
        } catch (SQLException e){
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errGetMainTable")+"\n"+e.getMessage());
        }
        return listModel;
    }

    /**
     * Créer une nouveau LotCuisson
     * @param p Produit concerné par la cuisson
     * @param nom_lot Nom du nouveau lot
     * @param quantite Quantite de produit en cuisson
     * @param lblStockVal le label de la valeur du stock
     * @return Le nouveau LotCuisson
     * */
    public LotCuisson ajouterCuisson(Produit p, String nom_lot, int quantite, JLabel lblStockVal) {
        if (quantite < 1) {
            return null;
        }
        if(p.getType() == TypeProduit.VIENNOISERIE){
            LotCuisson lot = null;
            try {
                Stock stock = this.daoStock.chercherStockParProduit(p).get(0);
                if (quantite <= stock.getQuantite()) {
                    lot = this.daoLotCuisson.ajouter(new LotCuisson(-1, nom_lot, quantite, p));
                    try {
                        stock.retirerAuStock(quantite);
                    } catch (SuppressionDansStockException e) {
                        FenetrePrincipale.afficherPopupErreur(this.cuissonBundle.getString("cuisson.stockinsuffisant") + " "+ e.getMessage());
                    }
                    this.daoStock.modifier(stock);
                    lblStockVal.setText(String.valueOf(stock.getQuantite()));
                }
            } catch (SQLException e) {
                FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errAjoutCuisson"));
                e.printStackTrace();
            }
            return lot;
        }
        else{
            FenetrePrincipale.afficherPopupErreur(this.cuissonBundle.getString("cuisson.erreurprog"));
            return null;
        }
    }

    /**
     * Renvoie la liste des LotCuisson
     * @return La liste des LotCuisson
     */
    public List<LotCuisson> getCuissons() {
        List<LotCuisson> l = new ArrayList<>();
        try {
            l = daoLotCuisson.chercher();
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errGetCuissons"));
            e.printStackTrace();
        }
        return l;
    }

    /**
     * Renvoie la liste des LotCuisson en cours de cuisson
     * @return La liste des cuissons en cours de cuisson
     */
    public List<LotCuisson> getCuissonsEnCours() {
        List<LotCuisson> l = new ArrayList<>();
        try {
            l = daoLotCuisson.chercher(false);
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errGetCuissonsEnCours"));
            e.printStackTrace();
        }
        return l;
    }

    /**
     * Renvoie la liste des LotCuisson archivés
     * @return La liste des LotCuisson archivés
     */
    public List<LotCuisson> getCuissonsArchives() {
        List<LotCuisson> l = new ArrayList<>();
        try {
            l = daoLotCuisson.chercher(true);
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errGetCuissons"));
            e.printStackTrace();
        }
        return l;
    }

    /**
     * Renvoie la liste des LotCuisson cuit à la date mentionée
     * @param date Date de cuisson des LotCuisson
     * @return Liste de LotCuisson en fonction de la date
     */
    public List<LotCuisson> getCuisson(Date date) {
        List<LotCuisson> l = new ArrayList<>();
        try {
            l = this.daoLotCuisson.chercher(date);
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errGetCuissonsDate"));
            e.printStackTrace();
        }
        return l;
    }

    /**
     * Supprime un LotCuisson
     * @param lot LotCuisson à supprimer
     */
    public void supprimerCuisson(LotCuisson lot) {
        try {
            this.daoLotCuisson.supprimer(lot);
            Perte perte = new Perte(-1, lot.getQuantite(), lot.getProduit(), new Date());
            this.daoPerte.ajouter(perte);
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errSupprCuisson"));
            e.printStackTrace();
        }
    }

    /**
     * Supprime un LotCuisson en fonction de son id
     * @param id id du LotCuisson à supprimer
     */
    public void supprimerCuisson(int id) {
        try {
            LotCuisson lot = this.daoLotCuisson.chercher(id);
            this.daoLotCuisson.supprimer(id);
            Perte perte = new Perte(-1, lot.getQuantite(), lot.getProduit(), new Date());
            this.daoPerte.ajouter(perte);
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errSupprCuisson"));
            e.printStackTrace();
        }
    }

    /**
     * Archive un LotCuisson
     * @param lot LotCuisson à archiver
     */
    public void archiverCuisson(LotCuisson lot) {
        lot.setEstArchive(true);
        try {
            this.daoLotCuisson.modifier(lot);
        } catch (SQLException e) {
            FenetrePrincipale.afficherPopupErreur(cuissonBundle.getString("cuisson.errArchivageCuisson"));
            e.printStackTrace();
        }
    }

    /**
     * Met un LotCuisson en vitrine
     * @param lotCuisson LotCuisson à mettre en vitrine
     */
    public void mettreEnVitrine(LotCuisson lotCuisson) {
        this.archiverCuisson(lotCuisson);
        LotVitrine lotVitrine = new LotVitrine(lotCuisson.getNom(), lotCuisson.getQuantite(), lotCuisson.getProduit());
        this.gVitrine.ajouterLotVitrine(lotVitrine);
    }
}
